import marked from 'marked'
import Prism from 'prismjs'
import 'prismjs/components/prism-javascript'
import 'prismjs/components/prism-python'
import 'prismjs/components/prism-c'
import 'prismjs/components/prism-bash'
import 'prismjs/themes/prism.css'

import {isPrimitive} from '@/core/utils'
// import {emojify} from "@/core/emojify"
import {slugify} from "@/core/slugify"

export class Compiler {
  constructor () {
    this.toc = []

    const renderer = this._initRenderer()
    marked.setOptions({
      renderer,
      sanitize: true
    })

    this.compile = (text) => {
      // clear the array
      this.toc.length = 0
      let html = ''

      if (!text) {
        return text
      }

      if (isPrimitive(text)) {
        html = marked(text)
      } else {
        html = marked.parser(text)
      }

      // html = emojify(html)
      slugify.clear()
      return html
    }
  }


  _initRenderer () {
    const renderer = new marked.Renderer()
    const origin = {}
    const self = this

    /**
     * Render anchor tag
     * @link https://github.com/markedjs/marked#overriding-renderer-methods
     */
    origin.heading = renderer.heading = function (text, level) {
      let slug = slugify(text)
      let url = '#' + slug
      let nextToc = {
        level,
        url,
        title: text,
        children: []
      }
      let t = self.toc[self.toc.length - 1]
      // have children, find the last children
      if (t && t.level < nextToc.level) {
        while (t.children.length) {
          let last_c = t.children[t.children.length - 1]
          if (last_c.level < nextToc.level) {
            t = last_c
          } else {
            break
          }
        }
        t.children.push(nextToc)
      } else {
        self.toc.push(nextToc)
      }
      return `<h${level} id="${slug}"><a href="${url}" data-id="${slug}" class="anchor"><span>${text}</span></a></h${level}>`
    }
    // Highlight code
    origin.code = renderer.code = function (code, lang = '') {
      const hl = Prism.highlight(
        code,
        Prism.languages[lang] || Prism.languages.markup
      )
      return `<pre v-pre class="language-${lang}"><code class="language-${lang}">${hl}</code></pre>`
    }

    const CHECKED_RE = /^\[([ x])\] +/
    origin.listitem = renderer.listitem = function (text) {
      const checked = CHECKED_RE.exec(text)
      if (checked) {
        text = text.replace(
          CHECKED_RE,
          `<input type="checkbox" ${checked[1] === 'x' ? 'checked' : ''} />`
        )
      }
      return `<li${checked ? ` class="task-list-item"` : ''}>${text}</li>\n`
    }

    renderer.origin = origin

    return renderer
  }
}

export const compiler = new Compiler()
